#!/bin/bash
#
# An IPFS Merkle DAG hash database and address manager, 
#
# Since I don't know if IPFS keeps a registry of all the DAGs and hashes I've
# ever accessed through it, I will do this manually as an "address book."
# Think of it like a bookmark manager of browsers, but on the CLI.
# 
# EDIT: as it turns out, there's some sort of bookkeeping on this, but it only
# works for pinned files (available as local storage). Also, it presents no 
# information on what that file might be, not even if it's a file at all 
# (as opposed to a folder). The command is:
#
#   ipfs pin ls
#
# As of current, you're better off "bookmarking" directories instead of single
# files. We will index these using the `ipfs ls` command.
#
# You can now tag the hash so as to make it more searchable. Separate tags with
# spaces. Also, so as to better categorize the kind of content you bookmark, 
# you must now supply a filetype MIME to the entry. This is free text and can
# easily be spoofed, but at least helps you to categorize the content. To be
# safe, always remember to check incoming files with the GNU `file' utility.
#
# Licensed as Free Software under the terms of the GNU GPL v3:
# 
#    Copyright (C) 2016 - Klaus Zimmermann
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# are we using mysql or sqlite3? (Others are unsupported yet)
BACKEND="sqlite3"

# change this value to suit your current sqlite3 configuration:
DB="$HOME/.ipfslinks.db"

# change these values to suit your current MySQL configuration:
MYSQL_USER=""
MYSQL_PASSWORD=""
MYSQL_SCHEMA=""


if [[ "$BACKEND" == "mysql" ]]
then
    if [[ -z "$MYSQL_PASSWORD" ]]; then
        DB_COMMAND="mysql -u $MYSQL_USER -D $MYSQL_SCHEMA -e"
    else
        DB_COMMAND="mysql -u $MYSQL_USER -p $MYSQL_PASSWORD -D $MYSQL_SCHEMA -e"
    fi
else
    DB_COMMAND="sqlite3 $DB"
fi

# -- functions --

create_table() {
    if [[ "$BACKEND" == "mysql" ]]
    then
        $DB_COMMAND "
        CREATE TABLE IF NOT EXISTS ipfs_tracker (
            id INTEGER PRIMARY KEY AUTO_INCREMENT,
            description VARCHAR(512) NOT NULL,
            hash VARCHAR(46) NOT NULL,
            filetype VARCHAR(12) NOT NULL,
            tags MEDIUMTEXT
        );
        "
    else
        $DB_COMMAND "
        CREATE TABLE IF NOT EXISTS ipfs_tracker (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            description TEXT NOT NULL,
            hash TEXT NOT NULL,
            filetype TEXT NOT NULL,
            tags TEXT
        );
        "
    fi
}

insert() {
    # Pass a description of the DAG and its hash as arguments.
    insert_query="INSERT INTO ipfs_tracker (description, hash, filetype, tags)
    VALUES ('$1', '$2', '$3', '$4');"
    $DB_COMMAND "$insert_query"
}

search() {
    # Pass a search text as the first argument.
    results="$($DB_COMMAND "SELECT description, hash, filetype FROM ipfs_tracker
        WHERE description LIKE '%$1%'
        OR tags LIKE '%$1%'")"
    if [[ -n "$results" ]]
    then
        echo "$results"
    else
        echo "Token '$1' not found."
    fi
}

delete() {
    # Pass an id number as the first argument.
    $DB_COMMAND "DELETE FROM ipfs_tracker WHERE id=$1" ||
        echo "Error: entry not found."
}

show_help() {
    echo "$(basename $0) - an IPFS address bookmarker"
    echo "USAGE: $(basename $0) COMMAND"
    echo "Commands are: 'init', 'register', 'search', 'delete'"
    echo "Written by Klaus Zimmermann - https://quitter.se/kzimmermann"
}

# -- /functions --

case "$1" in
    "--help" | "-h" ) 
        show_help
        exit 0
    ;;
    "register" )
        title=""
        dag_hash=""
        filetype=""
        tags=""
        while [[ -z "$title" ]]
        do
            printf "Type a short description of the entry: "
            read title
        done
        while [[ -z "$dag_hash" ]]
        do
            printf "Enter the hash of the entry: "
            read dag_hash
        done
        while [[ -z "$filetype" ]]
        do
            printf "Enter the file type of the entry (jpg, gif, pdf, zip...): "
            read filetype
        done
        while [[ -z "$tags" ]]
        do
            printf "Type a few tags to aid the searching of this entry later: "
            read tags
        done
        insert "$title" "$dag_hash" "$filetype" "$tags" ||
            echo "Error registering '$title'"
        exit 0
    ;;
    "search" )
        printf "Enter a string to search for (empty for ALL): "
        read token
        search "$token"
        exit 0
    ;;
    "delete" )
        $DB_COMMAND "SELECT id, description FROM ipfs_tracker"
        printf "Enter the id you would like to delete: "
        read del_id
        delete "$del_id"
        exit 0
    ;;
    "init" )
        create_table && echo "All necessary tables initialized."
        exit 0
    ;;
    * )
        echo "Unknown option '$1'"
        show_help
        exit 1
    ;;
esac
